/*  SSNeedsDiamond.m
 *  MESLib
 * 
 * Copyright 2003-2009 Starline Software Ltd
 * 
 * This file is part of MESLib.
 * 
 * MESLib is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * MESLib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with MESLib. If not, see <http://www.gnu.org/licenses/>.
 */
//  Created by Tobias Haughton on Wed Mar 19 2003.
//  Copyright (c) 2003 Starline Software. All rights reserved.
// SSNeedsDiamonds are primarily model objects containing the data for a single diamond, they also however
//have the ability to draw a representation of themselves in an nsview

#import "SSNeedsDiamond.h"
#import "SSEventObject.h"
#import "SSEventLinkObject.h"

@implementation SSNeedsDiamond

- (id)init
{
   if (self = [super init]) {
      isLoading = YES;
      [self setDiamondState:[NSNumber numberWithInt:SSNeedsDiamondDraftState]];
      [self setOptionArray:[NSMutableArray array]];
      isLoading = NO;
   }
   return self;
}

- (id)initWithOwner:(id)own
{
   if (self = [super init]) {
      isLoading = YES;
      [self setOwner:own];
      [self setDiamondState:[NSNumber numberWithInt:SSNeedsDiamondDraftState]];
      [self setOptionArray:[NSMutableArray array]];
      [self setUdValue1:[NSString string]];
      [self setUdValue2:[NSString string]];
      [self setUdValue3:[NSString string]];
      [self setUdValue4:[NSString string]];
      [self setUdValue5:[NSString string]];
      [self setUdValue6:[NSString string]];
      isLoading = NO;
   }
   return self;
}

- (id)initWithOwner:(id)own number:(NSNumber *)num
{
   if (self = [super init]) {
      isLoading = YES;
      [self setOwner:own];
      [self setNumber:num];
      [self setDiamondState:[NSNumber numberWithInt:SSNeedsDiamondDraftState]];
      [self setOptionArray:[NSMutableArray array]];
      [self setUdValue1:[NSString string]];
      [self setUdValue2:[NSString string]];
      [self setUdValue3:[NSString string]];
      [self setUdValue4:[NSString string]];
      [self setUdValue5:[NSString string]];
      [self setUdValue6:[NSString string]];
      isLoading = NO;
   }
   return self;
}

- (id)initWithOwner:(id)own fileID:(NSString *)file analyst:(NSString *)an description:(NSString *)des optionArray:(NSMutableArray *)options  diamondState:(NSNumber *)state
{
   if (self = [super init]) {
      isLoading = YES;
      [self setOwner:own];
      [self setFileID:file];
      [self setAnalyst:an];
      [self setDescription:des];
      [self setOptionArray:options];
      [self setDiamondState:state];
      [self setUdValue1:[NSString string]];
      [self setUdValue2:[NSString string]];
      [self setUdValue3:[NSString string]];
      [self setUdValue4:[NSString string]];
      [self setUdValue5:[NSString string]];
      [self setUdValue6:[NSString string]];
      isLoading = NO;
   }
   return self;
}

- (id)initWithOwner:(id)own
             fileID:(NSString *)file
            analyst:(NSString *)an
        description:(NSString *)des
           udValue1:(NSString *)ud1
           udValue2:(NSString *)ud2
           udValue3:(NSString *)ud3
           udValue4:(NSString *)ud4
           udValue5:(NSString *)ud5
           udValue6:(NSString *)ud6
        optionArray:(NSMutableArray *)options
       diamondState:(NSNumber *)state
{
   if (self = [super init]) {
      isLoading = YES;
      [self setOwner:own];
      [self setFileID:file];
      [self setAnalyst:an];
      [self setDescription:des];
      [self setOptionArray:options];
      [self setDiamondState:state];
      [self setUdValue1:ud1];
      [self setUdValue2:ud2];
      [self setUdValue3:ud3];
      [self setUdValue4:ud4];
      [self setUdValue5:ud5];
      [self setUdValue6:ud6];
      isLoading = NO;
   }
   return self;
}

- (void)draw
{
   int numXPos, numYPos, fontPoint;
   NSPoint origin = [self origin];
   NSBezierPath *border = [[[NSBezierPath alloc] init] autorelease];
   NSColor *diamondColor;
   
   //get positions / size for text
   if([[self number] intValue] < 10) {
      numXPos = origin.x + 7;
      numYPos = origin.y + 4;
      fontPoint = 10;
   } else if([[self number] intValue] < 100) {
      numXPos = origin.x + 4;
      numYPos = origin.y + 4;
      fontPoint = 10;
   } else {
      numXPos = origin.x + 3;
      numYPos = origin.y + 5;
      fontPoint = 8;
   }

   //create the path
   [border moveToPoint:NSMakePoint((origin.x + (SSNeedsDiamondSize.width / 2)), origin.y)];
   [border lineToPoint:NSMakePoint((origin.x + SSNeedsDiamondSize.width), (origin.y + (SSNeedsDiamondSize.height / 2)))];
   [border lineToPoint:NSMakePoint((origin.x + (SSNeedsDiamondSize.width / 2)), (origin.y + SSNeedsDiamondSize.height))];
   [border lineToPoint:NSMakePoint(origin.x, (origin.y + (SSNeedsDiamondSize.height / 2)))];
   [border lineToPoint:NSMakePoint((origin.x + (SSNeedsDiamondSize.width / 2)), origin.y)];


   if(![self isSelected]) {
      if([[self diamondState] intValue] == SSNeedsDiamondDraftState) {
         //it is open so draw a light yellow
         [[NSColor colorWithCalibratedRed:1.0 green:1.0 blue:0.8 alpha:1] set];
      } else {
         //it is done so draw white
         [[NSColor whiteColor] set];
      }
   } else {
      [SSSelectedColor set];
   }
   
   [border fill];
   
   if([[self diamondState] intValue] == SSNeedsDiamondDraftState) {
      diamondColor = [NSColor redColor]; 
   } else {
      diamondColor = [NSColor blackColor];
   }

   [diamondColor set];
   
   [border stroke];

   [[number stringValue] drawAtPoint:NSMakePoint(numXPos, numYPos)
                      withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[NSFont fontWithName:@"Helvetica" size:fontPoint],
                         NSFontAttributeName, diamondColor,
                         NSForegroundColorAttributeName, nil, nil]]; //draw our number
}

- (id)owner
{
   return owner;
}

- (NSNumber *)number
{
   return number;
}

- (NSString *)numberString
{
   return [number stringValue];
}

- (NSString *)fileID
{
   return fileID;
}

- (NSString *)analyst
{
   return analyst;   
}

- (NSString *)description
{
   return description;
}

- (NSNumber *)diamondState
{
   return diamondState;
}

- (NSString *)diamondStateString
{
   if([[self diamondState] intValue] == SSNeedsDiamondDraftState) {
      return @"draft";
   } else {
      return @"final";
   }
}

- (NSString *)ownerType
{
   if([owner isKindOfClass:[SSEventObject class]]) {
      return @"Event Block";
   } else {
      return @"Link";
   }
}

- (NSMutableArray *)optionArray
{
   return optionArray;   
}

- (NSString *)ownerDescription
{
   if([owner isKindOfClass:[SSEventObject class]]) {
      return [NSString stringWithFormat:@"%@\n%@", [(SSEventObject *)owner actor], [(SSEventObject *)owner action]];
   } else {
      return [NSString stringWithFormat:@"From: %@ - %@\nTo: %@ - %@", [(SSEventObject *)[owner linkedFrom] actor], [(SSEventObject *)[owner linkedFrom] action],
         [(SSEventObject *)[owner linkedTo] actor], [(SSEventObject *)[owner linkedTo] action]];
   }
}

- (NSString *)ownerDescriptionForCSV
{
   if([owner isKindOfClass:[SSEventObject class]]) {
      return [NSString stringWithFormat:@"%@ - %@", [(SSEventObject *)owner actor], [(SSEventObject *)owner action]];
   } else {
      return [NSString stringWithFormat:@"From: %@ - %@ To: %@ - %@", [(SSEventObject *)[owner linkedFrom] actor], [(SSEventObject *)[owner linkedFrom] action],
         [(SSEventObject *)[owner linkedTo] actor], [(SSEventObject *)[owner linkedTo] action]];
   }
}

- (NSString *)udValue1
{
   return udValue1;
}

- (NSString *)udValue2
{
   return udValue2;
}

- (NSString *)udValue3
{
   return udValue3;
}

- (NSString *)udValue4
{
   return udValue4;
}

- (NSString *)udValue5
{
   return udValue5;
}

- (NSString *)udValue6
{
   return udValue6;
}

- (void)setOwner:(id)own
{
   [owner release];
   [own retain];
   owner = own;
}

- (void)setNumber:(NSNumber *)num
{
   [number release];
   [num retain];
   number = num;
   [[NSNotificationCenter defaultCenter] postNotificationName:@"SSDiamondDataChanged"
                                                       object:nil];
}

- (void)setFileID:(NSString *)string
{
   [fileID release];
   [string retain];
   fileID = string;

   if(!isLoading) {
      [[NSNotificationCenter defaultCenter] postNotificationName:@"SSDiamondDataChanged"
                                                          object:nil];
      [[[NSDocumentController sharedDocumentController] currentDocument] updateChangeCount:NSChangeDone];
   }
}

- (void)setAnalyst:(NSString *)string
{
   [analyst release];
   [string retain];
   analyst = string;
   if(!isLoading) {
      [[NSNotificationCenter defaultCenter] postNotificationName:@"SSDiamondDataChanged"
                                                          object:nil];
      [[[NSDocumentController sharedDocumentController] currentDocument] updateChangeCount:NSChangeDone];
   }
}

- (void)setDiamondState:(NSNumber *)num
{
   [diamondState release];
   [num retain];
   diamondState = num;
   if(!isLoading) {
      [[NSNotificationCenter defaultCenter] postNotificationName:@"SSDiamondDataChanged"
                                                          object:nil];
      [[[NSDocumentController sharedDocumentController] currentDocument] updateChangeCount:NSChangeDone];
   }
}

- (void)switchDiamondState
{
   if([[self diamondState] intValue] == SSNeedsDiamondDraftState) {
      [self setDiamondState:[NSNumber numberWithInt:SSNeedsDiamondFinalState]];
   } else {
      [self setDiamondState:[NSNumber numberWithInt:SSNeedsDiamondDraftState]];
   }
}

- (void)setDescription:(NSString *)string
{
   [description release];
   [string retain];
   description = string;
   if(!isLoading) {
      [[NSNotificationCenter defaultCenter] postNotificationName:@"SSDiamondDataChanged"
                                                          object:nil];
      [[[NSDocumentController sharedDocumentController] currentDocument] updateChangeCount:NSChangeDone];
   }
}

- (void)setOptionArray:(NSMutableArray *)array
{
   [array retain];
   [optionArray release];
   optionArray = array;
}

- (void)addOption:(SSDiamondOption *)option
{
   [optionArray addObject:option];   
}

- (void)addNewOption
{
   SSDiamondOption *newOption = [[[SSDiamondOption alloc] init] autorelease];
   [optionArray addObject:newOption];
}

- (void)removeOption:(SSDiamondOption *)option
{
   [optionArray removeObject:option];
}


- (void)setUdValue1:(NSString *)string
{
   [string retain];
   [udValue1 release];
   udValue1 = string;

   if(!isLoading) {
      [[NSNotificationCenter defaultCenter] postNotificationName:@"SSDiamondDataChanged"
                                                          object:nil];
      [[[NSDocumentController sharedDocumentController] currentDocument] updateChangeCount:NSChangeDone];
   }
}

- (void)setUdValue2:(NSString *)string
{
   [string retain];
   [udValue2 release];
   udValue2 = string;

   if(!isLoading) {
      [[NSNotificationCenter defaultCenter] postNotificationName:@"SSDiamondDataChanged"
                                                          object:nil];
      [[[NSDocumentController sharedDocumentController] currentDocument] updateChangeCount:NSChangeDone];
   }
}

- (void)setUdValue3:(NSString *)string
{
   [string retain];
   [udValue3 release];
   udValue3 = string;

   if(!isLoading) {
      [[NSNotificationCenter defaultCenter] postNotificationName:@"SSDiamondDataChanged"
                                                          object:nil];
      [[[NSDocumentController sharedDocumentController] currentDocument] updateChangeCount:NSChangeDone];
   }
}

- (void)setUdValue4:(NSString *)string
{
   [string retain];
   [udValue4 release];
   udValue4 = string;

   if(!isLoading) {
      [[NSNotificationCenter defaultCenter] postNotificationName:@"SSDiamondDataChanged"
                                                          object:nil];
      [[[NSDocumentController sharedDocumentController] currentDocument] updateChangeCount:NSChangeDone];
   }
}

- (void)setUdValue5:(NSString *)string
{
   [string retain];
   [udValue5 release];
   udValue5 = string;

   if(!isLoading) {
      [[NSNotificationCenter defaultCenter] postNotificationName:@"SSDiamondDataChanged"
                                                          object:nil];
      [[[NSDocumentController sharedDocumentController] currentDocument] updateChangeCount:NSChangeDone];
   }
}

- (void)setUdValue6:(NSString *)string
{
   [string retain];
   [udValue6 release];
   udValue6 = string;

   if(!isLoading) {
      [[NSNotificationCenter defaultCenter] postNotificationName:@"SSDiamondDataChanged"
                                                          object:nil];
      [[[NSDocumentController sharedDocumentController] currentDocument] updateChangeCount:NSChangeDone];
   }
}

- (BOOL)isSelected
{
   return isSelected;
}

- (void)setSelected
{
   isSelected = YES;
}

- (void)setUnselected
{
   isSelected = NO;
}

//***********************************
- (BOOL)isFullyWithinRect:(NSRect)rect
{
   NSPoint origin = [self origin];

   if(origin.x > NSMinX(rect)) { //it's ok on the left
      if(origin.x + SSNeedsDiamondSize.width < NSMaxX(rect)) { //it's ok on the right
         if(origin.y > NSMinY(rect)) { //it's ok at the bottom
            if(origin.y + SSNeedsDiamondSize.height < NSMaxY(rect)) { //it's ok at top
                                                                    //it's fullyWithinRect
               return YES;
            }
         }
      }
   }
   return NO;
}

- (BOOL)containsPoint:(NSPoint)point
{
   NSPoint origin = [self origin];
   
   if(point.x > origin.x) {
      if(point.x < (origin.x + SSNeedsDiamondSize.width)) { //it is within our x range
         if(point.y > origin.y) {
            if(point.y < (origin.y + SSNeedsDiamondSize.height)) {
               //we contain this point
               return YES;
            }
         }
      }
   }
   return NO;
}

- (NSRect)frame
{
   NSPoint origin = [self origin];
   return NSMakeRect(origin.x, origin.y, SSNeedsDiamondSize.width, SSNeedsDiamondSize.height);
}

- (NSPoint)origin
{
   if([owner respondsToSelector:@selector(positionForNeedsDiamond:)]) {
      return [owner positionForNeedsDiamond:self];
   }

   return NSZeroPoint;
}

- (NSString *)searchString
{
   //called when user searches diamond table
   NSString *searchString = [NSString string];
   searchString = [searchString stringByAppendingString:fileID];
   searchString = [searchString stringByAppendingString:analyst];
   searchString = [searchString stringByAppendingString:description];
   searchString = [searchString stringByAppendingString:udValue1];
   searchString = [searchString stringByAppendingString:udValue2];
   searchString = [searchString stringByAppendingString:udValue3];
   searchString = [searchString stringByAppendingString:udValue4];
   searchString = [searchString stringByAppendingString:udValue5];
   searchString = [searchString stringByAppendingString:udValue6];
   
   return searchString;
}

//***********************************
- (NSString *)xmlStringRepresentation
{
   NSString *xmlString = [NSString stringWithFormat:@"<diamond>\n\t<block_attachment type=\"%@\">\n", [self ownerType]];

   if([[self ownerType] isEqualToString:@"Event Block"]) {
      xmlString = [xmlString stringByAppendingString:[NSString stringWithFormat:@"\t\t<address>%@</address>\n", [(SSEventObject *)owner address]]];
   } else {
      //it's owner is a link so we need to have both the linked from and to objects
      xmlString = [xmlString stringByAppendingString:[NSString stringWithFormat:@"\t\t<address>%@--(link)--%@</address>\n", [[(SSEventLinkObject *)owner linkedFrom] address], [[(SSEventLinkObject *)owner linkedTo] address]]];
   }

   xmlString = [xmlString stringByAppendingString:[NSString stringWithFormat:@"\t</block_attachment>\n\t<file ID>%@</file ID>\n\t<analyst>%@</analyst>\n\t<problemState>%@</problemState>\n\t<description>%@</description>\n\t<udValue1>%@</udValue1>\n\t<udValue2>%@</udValue2>\n\t<udValue3>%@</udValue3>\n\t<udValue4>%@</udValue4>\n\t<udValue5>%@</udValue5>\n\t<udValue6>%@</udValue6>\n\t<options>%@</options>\n</diamond>\n",
      [self fileID], [self analyst], [self diamondStateString], [self description], [self udValue1], [self udValue2], [self udValue3], [self udValue4], [self udValue5], [self udValue6], [self optionsXMLString]]];

   return xmlString;
}

- (NSString *)optionsXMLString
{
   NSEnumerator *enumerator = [optionArray objectEnumerator];
   id anObject;
   NSString *xmlString = [NSString string];

   while (anObject = [enumerator nextObject]) {
      //add this objects xml string
      xmlString = [xmlString stringByAppendingString:[anObject xmlStringRepresentation]];
   }

   return xmlString;
}


//***********************************coding
- (void)encodeWithCoder:(NSCoder *)coder
{
   [coder encodeObject:owner forKey:@"owner"];
   [coder encodeObject:number forKey:@"number"];
   [coder encodeObject:fileID forKey:@"fileNumber"];
   [coder encodeObject:analyst forKey:@"definer"];
   [coder encodeObject:description forKey:@"description"];
   [coder encodeObject:diamondState forKey:@"problemState"];
   [coder encodeObject:udValue1 forKey:@"udValue1"];
   [coder encodeObject:udValue2 forKey:@"udValue2"];
   [coder encodeObject:udValue3 forKey:@"udValue3"];
   [coder encodeObject:udValue4 forKey:@"udValue4"];
   [coder encodeObject:udValue5 forKey:@"udValue5"];
   [coder encodeObject:udValue6 forKey:@"udValue6"];
   [coder encodeObject:optionArray forKey:@"optionArray"];
}

- (id)initWithCoder:(NSCoder *)coder
{
   if(self = [super init]) {
      [self setOwner:[coder decodeObjectForKey:@"owner"]];
      [self setNumber:[coder decodeObjectForKey:@"number"]];
      [self setFileID:[coder decodeObjectForKey:@"fileNumber"]];
      [self setAnalyst:[coder decodeObjectForKey:@"definer"]];
      [self setDescription:[coder decodeObjectForKey:@"description"]];
      [self setDiamondState:[coder decodeObjectForKey:@"problemState"]];

      if([coder containsValueForKey:@"udValue1"]) {
         [self setUdValue1:[coder decodeObjectForKey:@"udValue1"]];
      } else {
         [self setUdValue1:[NSString string]];
      }

      if([coder containsValueForKey:@"udValue2"]) {
         [self setUdValue2:[coder decodeObjectForKey:@"udValue2"]];
      } else {
         [self setUdValue2:[NSString string]];
      }

      if([coder containsValueForKey:@"udValue3"]) {
         [self setUdValue3:[coder decodeObjectForKey:@"udValue3"]];
      } else {
         [self setUdValue3:[NSString string]];
      }

      if([coder containsValueForKey:@"udValue4"]) {
         [self setUdValue4:[coder decodeObjectForKey:@"udValue4"]];
      } else {
         [self setUdValue4:[NSString string]];
      }

      if([coder containsValueForKey:@"udValue5"]) {
         [self setUdValue5:[coder decodeObjectForKey:@"udValue5"]];
      } else {
         [self setUdValue5:[NSString string]];
      }

      if([coder containsValueForKey:@"udValue6"]) {
         [self setUdValue6:[coder decodeObjectForKey:@"udValue6"]];
      } else {
         [self setUdValue6:[NSString string]];
      }

      if([coder containsValueForKey:@"optionArray"]) {
         [self setOptionArray:[coder decodeObjectForKey:@"optionArray"]];
      } else {
         [self setOptionArray:[NSMutableArray array]];
      }
   }
   return self;
}

//***********************************

- (void)dealloc
{
   [owner release];
   [number release];
   [fileID release];
   [analyst release];
   [description release];
   [optionArray release];
   [udValue1 release];
   [udValue2 release];
   [udValue3 release];
   [udValue4 release];
   [udValue5 release];
   [udValue6 release];
   [super dealloc];
}


@end
